1
//--------------------------------------------------------------------------
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // File: ParallelGrep.cs
7 //--------------------------------------------------------------------------
12 using System
.Text
.RegularExpressions
;
13 using System
.Threading
;
17 static void Main(string[] args
)
19 // Parse command-line switches
20 bool recursive
= args
.Contains("/s");
21 bool ignoreCase
= args
.Contains("/i");
23 // Get the regex and file wildcards from the command-line
24 var nonSwitches
= from arg
in args where arg
.FirstOrDefault() != '/' select arg
;
25 var regexString
= nonSwitches
.FirstOrDefault();
26 var wildcards
= nonSwitches
.Skip(1);
28 // Create thread-local Regex instances, to prevent contention on Regex's internal lock
29 var regex
= new ThreadLocal
<Regex
>(() =>
30 new Regex(regexString
, RegexOptions
.Compiled
| (ignoreCase
? RegexOptions
.IgnoreCase
: RegexOptions
.None
)));
32 // Get the list of files to be examined
33 var files
= from wc
in wildcards
34 let dirName
= Path
.GetDirectoryName(wc
)
35 let fileName
= Path
.GetFileName(wc
)
36 from file
in Directory
.EnumerateFiles(
37 String
.IsNullOrWhiteSpace(dirName
) ? "." : dirName
,
38 String
.IsNullOrWhiteSpace(fileName
) ? "*.*" : fileName
,
39 recursive
? SearchOption
.AllDirectories
: SearchOption
.TopDirectoryOnly
)
44 // Traverse the specified files in parallel, and run each line through the Regex, collecting line number info
45 // for each match (the Zip call counts the lines in each file)
46 var matches
= from file
in files
.AsParallel().AsOrdered().WithMergeOptions(ParallelMergeOptions
.NotBuffered
)
47 from line
in File
.ReadLines(file
).Zip(Enumerable
.Range(1, int.MaxValue
), (s
, i
) => new { Num = i, Text = s, File = file }
)
48 where regex
.Value
.IsMatch(line
.Text
)
50 foreach (var line
in matches
)
52 Console
.WriteLine("{0}:{1} {2}", line
.File
, line
.Num
, line
.Text
);
55 catch (AggregateException ae
)
57 ae
.Handle(e
=> { Console.WriteLine(e.Message); return true; }
);